/**
 * 问小球落到第M格的概率
 * 令Dij表示小球落到第i行第j个钉子的概率
 * Dij由三个部分构成
 * 如果S[i-1][j-1]有钉子，则 D[i-1][j-1] / 2 对ij有贡献
 * 如果S[i-1][j]有钉子，则 D[i-1][j] / 2 对ij有贡献
 * 如果S[i-2][j-1]没有钉子，则 D[i-2][j-1] 对ij有贡献
 * 最后 D[N][M] 为答案
 * D[0][0] = 1
 * 注意边界判断，分数中直接乘会超过longlong，因此用int128
 */
#include <bits/stdc++.h>
using namespace std;

using llt = __int128_t;
using pii = pair<int, int>;
using vi = vector<int>;

llt const INF = 0x1F2F3F4F5F6F7F8F;
llt const NINF = -INF;

int N, M;
vector<string> S;

struct Rational{
    llt fenzi;
    llt fenmu;
    static const Rational & neg_one(){
        static const Rational NEG_ONE(-1, 1);
        return NEG_ONE;
    } 
    static const Rational & one(){
        static const Rational ONE(1, 1);
        return ONE;
    } 
    static const Rational & zero(){
        static const Rational ZERO(0, 1);
        return ZERO;
    } 
    static const Rational & one_second(){
        static const Rational ONE_SECOND(1, 2);
        return ONE_SECOND;
    }
    Rational(llt a, llt b): fenzi(a), fenmu(b){
        auto g = __gcd(a, b);
        fenzi /= g;
        fenmu /= g;
    }
    const Rational operator * (const Rational & r) const {
        return Rational(fenzi * r.fenzi, fenmu * r.fenmu);
    }
    Rational & operator += (const Rational & r){
        auto a = fenzi * r.fenmu + fenmu * r.fenzi;
        auto b = fenmu * r.fenmu;
        auto g = __gcd(a, b);
        fenzi = a / g;
        fenmu = b / g;
        return * this;
    }
    bool operator == (const Rational & r) const {
        return fenzi == r.fenzi and fenmu == r.fenmu;
    }
    bool operator != (const Rational & r) const {
        return ! this->operator==(r);
    }
};

ostream & operator << (ostream & os, const Rational & r){
    return os << (unsigned long long)r.fenzi << "/" << (unsigned long long)r.fenmu;
}



vector<vector<Rational>> D;

Rational dfs(int r, int c){
    assert(r >= c);
#ifndef ONLINE_JUDGE
    cout << "dfs(r = " << r << ", c = " << c << ")" << endl;
#endif
    if(D[r][c] != Rational::neg_one()) return D[r][c];

    auto & d = D[r][c];
    d = Rational::zero();
    if(r > 0 and c > 0 and S[r - 1][c - 1] == '*'){
        d += Rational::one_second() * dfs(r - 1, c - 1);
    }
    if(r > 0 and c < r and S[r - 1][c] == '*'){
        d += Rational::one_second() * dfs(r - 1, c);
    }
    if(r >= 2 and c >= 1 and r - 2 >= c - 1 and S[r - 2][c - 1] != '*'){
        d += dfs(r - 2, c - 1);
    }
    return d;
}

void proc(string & s){
    int k = 0;
    int n = s.length();
    for(auto c : s){
        if(c != ' '){
            s[k++] = c;
        }
    }
    s.erase(s.begin() + k, s.end());
    return;
}

void work(){
    cin >> N >> M;
    S.assign(N, {});
    getline(cin, S[0]);
    for(auto & s : S) {
        getline(cin, s);
        proc(s);
    }
    D.assign(N + 1, vector<Rational>(N + 1, Rational::neg_one()));
    D[0][0] = Rational::one();
    auto ans = dfs(N, M);
    cout << ans << endl;    
    return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase; 
    while(nofkase--) work();
    return 0;
}
